/**
 * Author: Dmitry Ustimov
 * Date: 5/22/13
 * Time: 2:17 PM
 */

package com.gmail.dmitryustimov.ms.java7.visitor.mod_actionmap.work.demo.structure1_2_4_8_16;

import com.gmail.dmitryustimov.ms.java7.patternslib.visitor.actionmap.VisitAction;

import java.util.HashMap;
import java.util.Map;

public class ConcreteElementVisitor<T> extends ElementVisitor<T> {

    public <S extends T> ConcreteElementVisitor() {
        Map<Class<? extends T>, VisitAction<? extends T>> actions = new HashMap<>();
        actions.put((Class<S>)ElementRoot.class,  (VisitAction<S>)this.new ElementRootVisitor());
        actions.put((Class<S>)ElementA.class,     (VisitAction<S>)this.new ElementAVisitor());
        actions.put((Class<S>)ElementA1.class,    (VisitAction<S>)this.new ElementA1Visitor());
        actions.put((Class<S>)ElementA11.class,   (VisitAction<S>)this.new ElementA11Visitor());
        actions.put((Class<S>)ElementA111.class,  (VisitAction<S>)this.new ElementA111Visitor());
        actions.put((Class<S>)ElementA112.class,  (VisitAction<S>)this.new ElementA112Visitor());
        actions.put((Class<S>)ElementA12.class,   (VisitAction<S>)this.new ElementA12Visitor());
        actions.put((Class<S>)ElementA121.class,  (VisitAction<S>)this.new ElementA121Visitor());
        actions.put((Class<S>)ElementA122.class,  (VisitAction<S>)this.new ElementA122Visitor());
        actions.put((Class<S>)ElementA2.class,    (VisitAction<S>)this.new ElementA2Visitor());
        actions.put((Class<S>)ElementA21.class,   (VisitAction<S>)this.new ElementA21Visitor());
        actions.put((Class<S>)ElementA211.class,  (VisitAction<S>)this.new ElementA211Visitor());
        actions.put((Class<S>)ElementA212.class,  (VisitAction<S>)this.new ElementA212Visitor());
        actions.put((Class<S>)ElementA22.class,   (VisitAction<S>)this.new ElementA22Visitor());
        actions.put((Class<S>)ElementA221.class,  (VisitAction<S>)this.new ElementA221Visitor());
        actions.put((Class<S>)ElementA222.class,  (VisitAction<S>)this.new ElementA222Visitor());
        actions.put((Class<S>)ElementB.class,     (VisitAction<S>)this.new ElementBVisitor());
        actions.put((Class<S>)ElementB1.class,    (VisitAction<S>)this.new ElementB1Visitor());
        actions.put((Class<S>)ElementB11.class,   (VisitAction<S>)this.new ElementB11Visitor());
        actions.put((Class<S>)ElementB111.class,  (VisitAction<S>)this.new ElementB111Visitor());
        actions.put((Class<S>)ElementB112.class,  (VisitAction<S>)this.new ElementB112Visitor());
        actions.put((Class<S>)ElementB12.class,   (VisitAction<S>)this.new ElementB12Visitor());
        actions.put((Class<S>)ElementB121.class,  (VisitAction<S>)this.new ElementB121Visitor());
        actions.put((Class<S>)ElementB122.class,  (VisitAction<S>)this.new ElementB122Visitor());
        actions.put((Class<S>)ElementB2.class,    (VisitAction<S>)this.new ElementB2Visitor());
        actions.put((Class<S>)ElementB21.class,   (VisitAction<S>)this.new ElementB21Visitor());
        actions.put((Class<S>)ElementB211.class,  (VisitAction<S>)this.new ElementB211Visitor());
        actions.put((Class<S>)ElementB212.class,  (VisitAction<S>)this.new ElementB212Visitor());
        actions.put((Class<S>)ElementB22.class,   (VisitAction<S>)this.new ElementB22Visitor());
        actions.put((Class<S>)ElementB221.class,  (VisitAction<S>)this.new ElementB221Visitor());
        actions.put((Class<S>)ElementB222.class,  (VisitAction<S>)this.new ElementB222Visitor());
        init(actions);
    }

    private void printElement(Element element) {
    }

    public class ElementRootVisitor implements VisitAction<ElementRoot> {
        @Override
        public void visit(ElementRoot element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementAVisitor implements VisitAction<ElementA> {
        @Override
        public void visit(ElementA element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementBVisitor implements VisitAction<ElementB> {
        @Override
        public void visit(ElementB element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementA1Visitor implements VisitAction<ElementA1> {
        @Override
        public void visit(ElementA1 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementA11Visitor implements VisitAction<ElementA11> {
        @Override
        public void visit(ElementA11 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementA111Visitor implements VisitAction<ElementA111> {
        @Override
        public void visit(ElementA111 element) {
            printElement(element);
        }
    }

    public class ElementA112Visitor implements VisitAction<ElementA112> {
        @Override
        public void visit(ElementA112 element) {
            printElement(element);
        }
    }

    public class ElementA12Visitor implements VisitAction<ElementA12> {
        @Override
        public void visit(ElementA12 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementA121Visitor implements VisitAction<ElementA121> {
        @Override
        public void visit(ElementA121 element) {
            printElement(element);
        }
    }

    public class ElementA122Visitor implements VisitAction<ElementA122> {
        @Override
        public void visit(ElementA122 element) {
            printElement(element);
        }
    }

    public class ElementB1Visitor implements VisitAction<ElementB1> {
        @Override
        public void visit(ElementB1 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementB11Visitor implements VisitAction<ElementB11> {
        @Override
        public void visit(ElementB11 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementB111Visitor implements VisitAction<ElementB111> {
        @Override
        public void visit(ElementB111 element) {
            printElement(element);
        }
    }

    public class ElementB112Visitor implements VisitAction<ElementB112> {
        @Override
        public void visit(ElementB112 element) {
            printElement(element);
        }
    }

    public class ElementB12Visitor implements VisitAction<ElementB12> {
        @Override
        public void visit(ElementB12 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementB121Visitor implements VisitAction<ElementB121> {
        @Override
        public void visit(ElementB121 element) {
            printElement(element);
        }
    }

    public class ElementB122Visitor implements VisitAction<ElementB122> {
        @Override
        public void visit(ElementB122 element) {
            printElement(element);
        }
    }

    public class ElementA2Visitor implements VisitAction<ElementA2> {
        @Override
        public void visit(ElementA2 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementA21Visitor implements VisitAction<ElementA21> {
        @Override
        public void visit(ElementA21 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementA211Visitor implements VisitAction<ElementA211> {
        @Override
        public void visit(ElementA211 element) {
            printElement(element);
        }
    }

    public class ElementA212Visitor implements VisitAction<ElementA212> {
        @Override
        public void visit(ElementA212 element) {
            printElement(element);
        }
    }

    public class ElementA22Visitor implements VisitAction<ElementA22> {
        @Override
        public void visit(ElementA22 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementA221Visitor implements VisitAction<ElementA221> {
        @Override
        public void visit(ElementA221 element) {
            printElement(element);
        }
    }

    public class ElementA222Visitor implements VisitAction<ElementA222> {
        @Override
        public void visit(ElementA222 element) {
            printElement(element);
        }
    }

    public class ElementB2Visitor implements VisitAction<ElementB2> {
        @Override
        public void visit(ElementB2 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementB21Visitor implements VisitAction<ElementB21> {
        @Override
        public void visit(ElementB21 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementB211Visitor implements VisitAction<ElementB211> {
        @Override
        public void visit(ElementB211 element) {
            printElement(element);
        }
    }

    public class ElementB212Visitor implements VisitAction<ElementB212> {
        @Override
        public void visit(ElementB212 element) {
            printElement(element);
        }
    }

    public class ElementB22Visitor implements VisitAction<ElementB22> {
        @Override
        public void visit(ElementB22 element) {
            printElement(element);
            visitElements(element, ConcreteElementVisitor.this);
        }
    }

    public class ElementB221Visitor implements VisitAction<ElementB221> {
        @Override
        public void visit(ElementB221 element) {
            printElement(element);
        }
    }

    public class ElementB222Visitor implements VisitAction<ElementB222> {
        @Override
        public void visit(ElementB222 element) {
            printElement(element);
        }
    }
}
